﻿using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

namespace MetadataDesignerLibrary
{
    public class LocalScopeRule : ILRule<LocalScopeHandle>
    {
        [ILInfo(true)]
        public int StartOffset { get; }

        [ILInfo(true)]
        public int Length { get; }

        [ILInfo(ILInfoParseMethod.AsEntityHandle)]
        public MethodDefinitionHandle Method { get; }

        [ILInfo(ILInfoParseMethod.AsEntityHandle)]
        public ImportScopeHandle ImportScope { get; }

        [ILInfo(ILInfoParseMethod.AsEntityHandleCollection)]
        public LocalVariableHandleCollection LocalVariables { get; }

        [ILInfo(ILInfoParseMethod.AsEntityHandleCollection)]
        public LocalConstantHandleCollection LocalConstants { get; }

        [ILInfo]
        public int EndOffset { get; }

        [ILInfo(ILInfoParseMethod.AsEntityHandleCollection)]
        public LocalScopeHandleCollection.ChildrenEnumerator Children { get; }

        public LocalScopeRule(
            MethodDefinitionHandle method,
            ImportScopeHandle importScope,
            int startOffset,
            int length)
            : base()
        {
            Method = method;
            ImportScope = importScope;
            StartOffset = startOffset;
            Length = length;
        }

        public LocalScopeRule(MetadataReader reader, LocalScopeHandle localScopeHandle)
            : base(reader)
        {
            LocalScope localScope = reader.GetLocalScope(localScopeHandle);
            Method = localScope.Method;
            ImportScope = localScope.ImportScope;
            StartOffset = localScope.StartOffset;
            Length = localScope.Length;
            EndOffset = localScope.EndOffset;
            LocalVariables = localScope.GetLocalVariables();
            LocalConstants = localScope.GetLocalConstants();
            Children = localScope.GetChildren();
        }

        public override LocalScopeHandle Write(MetadataDesigner designer)
        {
            MetadataBuilder builder = designer.Builder;
            LocalScopeHandle localScopeHandle = builder.AddLocalScope(
                importScope: ImportScope,
                method: Method,
                variableList: MetadataTokens.LocalVariableHandle(designer.LocalVariableNumber.First),
                constantList: MetadataTokens.LocalConstantHandle(designer.LocalConstantNumber.First),
                startOffset: StartOffset,
                length: Length);
            designer.LocalVariableNumber.Next();
            designer.LocalConstantNumber.Next();
            return localScopeHandle;
        }
    }
}